package com.wnxy.admin.listener;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.rabbitmq.client.Channel;
import com.wnxy.admin.config.MessageQueueConfig;
import com.wnxy.admin.entity.AlarmMessages;
import com.wnxy.admin.entity.MaintenancePersonnel;
import com.wnxy.admin.entity.MaintenanceTasks;
import com.wnxy.admin.service.IAlarmMessagesService;
import com.wnxy.admin.service.IMaintenancePersonnelService;
import com.wnxy.admin.service.IMaintenanceTasksService;
import com.wnxy.admin.vo.AlertEnum;
import lombok.RequiredArgsConstructor;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;

@Component
@RequiredArgsConstructor
public class MessageProcessingListener {

    private final IMaintenancePersonnelService maintenancePersonnelServiceImpl;
    private final IMaintenanceTasksService maintenanceTasksServiceImpl;
    private final JavaMailSender javaMailSender;
    private final IAlarmMessagesService alarmMessagesServiceImpl;

    @Value("${spring.mail.username}")
    private String email;

    // RabbitMQ 消息监听器
    @RabbitListener(queues = MessageQueueConfig.DELAY_QUEUE)
    public void processDelayedMessage(String message, Channel channel,
                                      @Header(AmqpHeaders.DELIVERY_TAG) Long deliveryTag) throws IOException {
        try {
            AlarmMessages alarmMessages = JSONUtil.toBean(message, AlarmMessages.class);

            // 生成 MaintenanceTasks 对象
            MaintenanceTasks maintenanceTasks = generateMaintenanceTask(alarmMessages);

            // 将生成的任务存入任务管理
            maintenanceTasksServiceImpl.save(maintenanceTasks);

            // 获取空闲状态的运维人员列表
            List<MaintenancePersonnel> maintenancePersonnelList = getEnabledMaintenancePersonnel();

            // 如果有可用的人员，分配任务；否则挂起任务
            if (!maintenancePersonnelList.isEmpty()) {
                assignTaskToPersonnel(maintenanceTasks, maintenancePersonnelList);
            } else {
                suspendTask(maintenanceTasks);
            }
        }finally {
            // 手动确认消息
            // 即使发生异常，也要确保消息被确认，以防止重复处理
            channel.basicAck(deliveryTag, false);
        }
    }

    // 根据 AlarmMessages 生成 MaintenanceTasks
    private MaintenanceTasks generateMaintenanceTask(AlarmMessages alarmMessages) {
        MaintenanceTasks maintenanceTasks = new MaintenanceTasks();
        maintenanceTasks.setTaskAlarmId(alarmMessages.getMessageId());
        maintenanceTasks.setTaskName(alarmMessages.getChargerName() +
                (alarmMessages.getLevelDegree() == -1 ? AlertEnum.Emergency_repair_tasks.getMsg() : AlertEnum.Firefighting_mission.getMsg()));
        maintenanceTasks.setTaskType((alarmMessages.getLevelDegree() == -1 ? AlertEnum.Emergency_repair_tasks.getMsg() : AlertEnum.Firefighting_mission.getMsg()));
        return maintenanceTasks;
    }

    // 获取空闲状态的运维人员列表
    private List<MaintenancePersonnel> getEnabledMaintenancePersonnel() {
        return maintenancePersonnelServiceImpl.list(Wrappers.lambdaQuery(MaintenancePersonnel.class)
                .eq(MaintenancePersonnel::getStatus, 2));
    }

    // 将任务分配给空闲运维人员
    private void assignTaskToPersonnel(MaintenanceTasks maintenanceTasks, List<MaintenancePersonnel> personnelList) {
        Collections.shuffle(personnelList);
        MaintenancePersonnel personnel = personnelList.get(0);

        // 分配任务详情
        maintenanceTasks.setTaskOperatorId(personnel.getOperatorId());
        maintenanceTasks.setStartTime(new Date());
        maintenanceTasks.setStatus(-1);

        // 更新人员状态//维修中
        personnel.setStatus(-1);
        maintenancePersonnelServiceImpl.updateById(personnel);

        // 在数据库中更新任务状态
        maintenanceTasksServiceImpl.updateById(maintenanceTasks);

        // 发送通知邮件
        String targetEmail = personnel.getContactEmail();
        sendMail(targetEmail);
    }

    // 如果没有可用的人员，挂起任务
    private void suspendTask(MaintenanceTasks maintenanceTasks) {
        // 检查数据库中是否已存在相同的任务记录
        MaintenanceTasks existingTask = maintenanceTasksServiceImpl.getOne(Wrappers.lambdaQuery(MaintenanceTasks.class)
                .eq(MaintenanceTasks::getTaskId, maintenanceTasks.getTaskId())
                .eq(MaintenanceTasks::getStatus, 0));

        if (existingTask == null) {
            // 将任务详情加入数据库
            maintenanceTasksServiceImpl.save(maintenanceTasks);
        }
    }

    // 定时任务，每天整点检查未处理任务
    @Scheduled(cron = "0 */2 * * * ?") 
    private void checkUnprocessedTasks() {
        // 检查数据库中是否存在未处理的任务
        List<MaintenanceTasks> unprocessedTasks = maintenanceTasksServiceImpl.list(Wrappers.lambdaQuery(MaintenanceTasks.class)
                .eq(MaintenanceTasks::getStatus, 0));

        // 如果存在未处理的任务
        if (!unprocessedTasks.isEmpty()) {
            // 根据任务的类型和报警时间进行排序
            unprocessedTasks.sort((task1, task2) -> {
                int typeComparison = compareTaskType(task1.getTaskType(), task2.getTaskType());
                if (typeComparison != 0) {
                    return typeComparison;
                } else {
                    // 如果任务类型相同，比较报警时间
                    AlarmMessages alarm1 = alarmMessagesServiceImpl.getOne(Wrappers.lambdaQuery(AlarmMessages.class)
                            .eq(AlarmMessages::getMessageId, task1.getTaskAlarmId()));
                    AlarmMessages alarm2 = alarmMessagesServiceImpl.getOne(Wrappers.lambdaQuery(AlarmMessages.class)
                            .eq(AlarmMessages::getMessageId, task2.getTaskAlarmId()));

                    return alarm1.getAlarmTime().compareTo(alarm2.getAlarmTime());
                }
            });

            // 获取空闲状态的运维人员列表
            List<MaintenancePersonnel> enabledPersonnel = getEnabledMaintenancePersonnel();

            if(!enabledPersonnel.isEmpty()) {
                // 遍历未处理任务，为每个任务分配人员
                for (MaintenanceTasks unprocessedTask : unprocessedTasks) {
                    assignTaskToPersonnel(unprocessedTask, enabledPersonnel);
                }
            }
            //无可用运维人员,挂起任务
        }
    }

    // 发送通知邮件
    private void sendMail(String targetEmail) {
        SimpleMailMessage smm = new SimpleMailMessage();
        smm.setFrom(email);
        smm.setTo(targetEmail);
        smm.setSubject("任务通知");
        smm.setSentDate(new Date());
        smm.setText("您已被分配运维任务，请及时处理，否则处死");
        javaMailSender.send(smm);
    }

    // 根据规则比较任务类型
    private int compareTaskType(String type1, String type2) {
        List<String> taskTypeOrder = Arrays.asList(
                AlertEnum.Emergency_repair_tasks.getMsg(),
                AlertEnum.Firefighting_mission.getMsg(),
                AlertEnum.Maintenance_tasks.getMsg()
        );

        return Integer.compare(taskTypeOrder.indexOf(type1), taskTypeOrder.indexOf(type2));
    }
}
